#pragma once

#include <functional>
#include "InetAddr.hpp"
#include "Socket.hpp"

static int gport = 8888;

using service_io_t = std::function<void(SockPtr, InetAddr &)>; // 不允许使用不完整的类型->Socket.hpp中的SockPtr没有声明

class Tcpserver
{
public:
    Tcpserver(service_io_t service, int port = gport)
        : _service(service), _port(port),
          _isrunning(false),
          _listensock(std::make_shared<TcpSocket>())
    {
        _listensock->BuildListenSocket(_port);
    }

    struct ThreadData
    {
        ThreadData(SockPtr sockfd, Tcpserver* self, const InetAddr& addr)
        :_sockfd(sockfd), _self(self), _addr(addr)
        {  
        }

        SockPtr _sockfd;
        Tcpserver *_self;
        InetAddr _addr; 
    };

    void Loop()
    {
        _isrunning = true;
        while(_isrunning)
        {
            InetAddr client;
            SockPtr newsock = _listensock->CreateAccept(&client);
            if(newsock == nullptr)
                continue;
            pthread_t tid;
            ThreadData* td = new ThreadData(newsock,this, client);
            pthread_create(&tid,nullptr, Excute, td);
        }
        _isrunning = false;
    }

    static void* Excute(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(args);
        td->_self->_service(td->_sockfd, td->_addr);
        td->_sockfd->Close();
        delete td; // 
        return nullptr;
    }

    ~Tcpserver()
    {
    }

private:
    uint16_t _port;
    bool _isrunning;
    SockPtr _listensock;
    service_io_t _service;
};